package com.bishe.service.impl;


import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.Month;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.bishe.config.DataException;
import com.bishe.pojo.BillType;
import com.bishe.pojo.UserBill;
import com.bishe.pojo.query.StatisticsQuery;
import com.bishe.service.BillTypeService;
import com.bishe.service.UserBillService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.TextStyle;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class StatisticsServiceImpl {


    private final static List<String> monthList = Arrays.asList("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12");

    @Resource
    private UserBillService userBillService;

    @Resource
    private BillTypeService billTypeService;

    /**
     * 按年、月查所有类型收入 支出
     */
    public Map<String, Object> findPayAndIncome(StatisticsQuery query) {

        List<UserBill> userBill = getUserBills(query);

        List<String> billTypes = billTypeService.list().stream().map(BillType::getTypeEn).collect(Collectors.toList());

        // 每个类型总支出
        Map<String, Object> resultMap = new HashMap<>();
        Map<String, List<UserBill>> typeGroupPay = userBill.stream().collect(Collectors.groupingBy(UserBill::getType));
        typeGroupPay.forEach((k, v) -> {
            if (CollUtil.isNotEmpty(v)) {
                billTypes.removeIf(k::equals);

                BigDecimal typePay = v.stream()
                        .filter(s -> s.getPm() == 1 && ObjectUtil.isNotEmpty(s.getNumber()))
                        .map(UserBill::getNumber)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                resultMap.put(k, NumberUtil.decimalFormat("#0.00", typePay));
            }
        });
        billTypes.forEach(k -> resultMap.put(k, "0.00"));

        // 每个类型的总收入
        Map<String, Object> typeSumIncome = new HashMap<>();
        Map<String, List<UserBill>> typeGroupIncome = userBill.stream().collect(Collectors.groupingBy(UserBill::getType));
        typeGroupIncome.forEach((k, v) -> {
            if (CollUtil.isNotEmpty(v)) {
                billTypes.removeIf(k::equals);

                BigDecimal typeIncome = v.stream()
                        .filter(s -> s.getPm() == 0 && ObjectUtil.isNotEmpty(s.getNumber()))
                        .map(UserBill::getNumber)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                typeSumIncome.put(k, NumberUtil.decimalFormat("#0.00", typeIncome));
            }
        });
        resultMap.put("income", typeSumIncome.get("income"));
        return resultMap;
    }


    /**
     * 按月返回每个类型的数量
     */
    public Map<String, Object> findTypeNumber(StatisticsQuery query) {
        List<UserBill> userBills = getUserBills(query);
        List<String> billTypes = billTypeService.list().stream().map(BillType::getTypeEn).collect(Collectors.toList());

        Map<String, Object> typeSumPay = new HashMap<>();
        Map<String, List<UserBill>> typeGroupPay = userBills.stream().collect(Collectors.groupingBy(UserBill::getType));
        typeGroupPay.forEach((k, v) -> {
            if (CollUtil.isNotEmpty(v)) {
                billTypes.removeIf(k::equals);

                typeSumPay.put(k, v.size());
            }
        });
        billTypes.forEach(k -> typeSumPay.put(k, "0"));
        return typeSumPay;
    }

    public Map<String, Object> nowYearData() {

        // 根据条件查询
        StpUtil.checkLogin();
        List<UserBill> userBill = userBillService.list(
                Wrappers.lambdaQuery(UserBill.class)
                        .eq(UserBill::getUid, StpUtil.getLoginIdAsString())
                        .between(UserBill::getBillDate,
                                DateUtil.format(DateUtil.beginOfYear(new Date()), DatePattern.NORM_DATE_PATTERN),
                                DateUtil.format(DateUtil.endOfYear(new Date()), DatePattern.NORM_DATE_PATTERN)));


        if (CollUtil.isEmpty(userBill)) {
            throw new DataException("该用户暂无账单数据。。。");
        }

        List<String> billTypes = billTypeService.list().stream().map(BillType::getTypeEn).collect(Collectors.toList());

        // 根据类型组
        Map<String, List<UserBill>> collect = userBill.stream()
                .collect(Collectors.groupingBy(UserBill::getType));

        Map<String, Object> resultMap = new HashMap<>();
        for (Map.Entry<String, List<UserBill>> entry : collect.entrySet()) {

            List<UserBill> userBills = entry.getValue();

            List<String> billTypeList = new ArrayList<>();
            for (String billType : billTypes) {
                if (!collect.containsKey(billType)) {
                    billTypeList.add(billType);
                }
            }


            if (CollUtil.isNotEmpty(userBills)) {
                Map<Integer, List<UserBill>> monthCollect = userBills.stream()
                        .collect(Collectors.groupingBy(s -> DateUtil.month(s.getBillDate())));

                // 填充月份数据
                for (String month : monthList) {
                    if (!monthCollect.containsKey(Integer.parseInt(month))) {
                        monthCollect.put(Integer.parseInt(month), new ArrayList<>());
                    }
                }

                // 根据月份分组 计算支出
                Map<Integer, Object> typeMap = new HashMap<>();
                monthCollect.forEach((k, v) -> {
                    if (CollUtil.isEmpty(v)) {
                        // 填充空月数据
                        typeMap.put(k, NumberUtil.decimalFormat("#0.00", BigDecimal.ZERO));
                    } else {
                        // 计算总和
                        BigDecimal reduce = v.stream()
                                .filter(s->ObjectUtil.isNotEmpty(s.getNumber()))
                                .map(UserBill::getNumber)
                                .reduce(BigDecimal.ZERO, BigDecimal::add);
                        typeMap.put(k, NumberUtil.decimalFormat("#0.00", reduce));
                    }
                });
                resultMap.put(entry.getKey(), typeMap);
            }
        }

        // 填充空属性月份数据
        Map<String, Object> templateData = new HashMap<>();
        monthList.forEach(s->templateData.put(s, NumberUtil.decimalFormat("#0.00", BigDecimal.ZERO)));

        for (String billType : billTypes) {
            if (!resultMap.containsKey(billType)) {
                resultMap.put(billType, templateData);
            }
        }
        return resultMap;
    }


    /**
     * 查询所有符合条件的bill
     *
     * @param query
     * @return
     */
    private List<UserBill> getUserBills(StatisticsQuery query) {
        StpUtil.checkLogin();
        List<UserBill> userBill = userBillService.list(
                Wrappers.lambdaQuery(UserBill.class)
                        .eq(UserBill::getUid, StpUtil.getLoginIdAsString())
                        .between(UserBill::getBillDate, query.getStartTime(), query.getEndTime())
                        .orderByDesc(UserBill::getBillDate)
        );

        if (CollUtil.isEmpty(userBill)) {
            throw new DataException("该用户暂无账单数据。。。");
        }
        return userBill;
    }
}
